using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace AuthService.Infrastructure.Monitoring;

/// <summary>
/// 指标收集器接口
/// </summary>
public interface IMetricsCollector
{
    /// <summary>
    /// 记录API请求
    /// </summary>
    /// <param name="endpoint">端点</param>
    /// <param name="method">HTTP方法</param>
    /// <param name="statusCode">状态码</param>
    /// <param name="duration">持续时间</param>
    void RecordApiRequest(string endpoint, string method, int statusCode, TimeSpan duration);

    /// <summary>
    /// 记录数据库操作
    /// </summary>
    /// <param name="operation">操作类型</param>
    /// <param name="table">表名</param>
    /// <param name="duration">持续时间</param>
    /// <param name="success">是否成功</param>
    void RecordDatabaseOperation(string operation, string table, TimeSpan duration, bool success);

    /// <summary>
    /// 记录外部服务调用
    /// </summary>
    /// <param name="serviceName">服务名称</param>
    /// <param name="operation">操作</param>
    /// <param name="duration">持续时间</param>
    /// <param name="success">是否成功</param>
    void RecordExternalServiceCall(string serviceName, string operation, TimeSpan duration, bool success);

    /// <summary>
    /// 增加计数器
    /// </summary>
    /// <param name="name">计数器名称</param>
    /// <param name="tags">标签</param>
    /// <param name="value">增加值</param>
    void IncrementCounter(string name, Dictionary<string, string>? tags = null, long value = 1);

    /// <summary>
    /// 记录直方图值
    /// </summary>
    /// <param name="name">直方图名称</param>
    /// <param name="value">值</param>
    /// <param name="tags">标签</param>
    void RecordHistogram(string name, double value, Dictionary<string, string>? tags = null);

    /// <summary>
    /// 设置仪表值
    /// </summary>
    /// <param name="name">仪表名称</param>
    /// <param name="value">值</param>
    /// <param name="tags">标签</param>
    void SetGauge(string name, double value, Dictionary<string, string>? tags = null);

    /// <summary>
    /// 获取指标摘要
    /// </summary>
    /// <returns>指标摘要</returns>
    MetricsSummary GetMetricsSummary();
}

/// <summary>
/// 指标摘要
/// </summary>
public class MetricsSummary
{
    /// <summary>
    /// API请求统计
    /// </summary>
    public ApiRequestMetrics ApiRequests { get; set; } = new();

    /// <summary>
    /// 数据库操作统计
    /// </summary>
    public DatabaseMetrics Database { get; set; } = new();

    /// <summary>
    /// 外部服务调用统计
    /// </summary>
    public ExternalServiceMetrics ExternalServices { get; set; } = new();

    /// <summary>
    /// 系统指标
    /// </summary>
    public SystemMetrics System { get; set; } = new();

    /// <summary>
    /// 收集时间
    /// </summary>
    public DateTime CollectedAt { get; set; } = DateTime.UtcNow;
}

/// <summary>
/// API请求指标
/// </summary>
public class ApiRequestMetrics
{
    /// <summary>
    /// 总请求数
    /// </summary>
    public long TotalRequests { get; set; }

    /// <summary>
    /// 成功请求数
    /// </summary>
    public long SuccessfulRequests { get; set; }

    /// <summary>
    /// 失败请求数
    /// </summary>
    public long FailedRequests { get; set; }

    /// <summary>
    /// 平均响应时间（毫秒）
    /// </summary>
    public double AverageResponseTime { get; set; }

    /// <summary>
    /// 最大响应时间（毫秒）
    /// </summary>
    public double MaxResponseTime { get; set; }

    /// <summary>
    /// 最小响应时间（毫秒）
    /// </summary>
    public double MinResponseTime { get; set; }

    /// <summary>
    /// 按端点分组的请求数
    /// </summary>
    public Dictionary<string, long> RequestsByEndpoint { get; set; } = new();

    /// <summary>
    /// 按状态码分组的请求数
    /// </summary>
    public Dictionary<int, long> RequestsByStatusCode { get; set; } = new();
}

/// <summary>
/// 数据库指标
/// </summary>
public class DatabaseMetrics
{
    /// <summary>
    /// 总操作数
    /// </summary>
    public long TotalOperations { get; set; }

    /// <summary>
    /// 成功操作数
    /// </summary>
    public long SuccessfulOperations { get; set; }

    /// <summary>
    /// 失败操作数
    /// </summary>
    public long FailedOperations { get; set; }

    /// <summary>
    /// 平均执行时间（毫秒）
    /// </summary>
    public double AverageExecutionTime { get; set; }

    /// <summary>
    /// 按操作类型分组的统计
    /// </summary>
    public Dictionary<string, long> OperationsByType { get; set; } = new();

    /// <summary>
    /// 按表分组的统计
    /// </summary>
    public Dictionary<string, long> OperationsByTable { get; set; } = new();
}

/// <summary>
/// 外部服务指标
/// </summary>
public class ExternalServiceMetrics
{
    /// <summary>
    /// 总调用数
    /// </summary>
    public long TotalCalls { get; set; }

    /// <summary>
    /// 成功调用数
    /// </summary>
    public long SuccessfulCalls { get; set; }

    /// <summary>
    /// 失败调用数
    /// </summary>
    public long FailedCalls { get; set; }

    /// <summary>
    /// 平均响应时间（毫秒）
    /// </summary>
    public double AverageResponseTime { get; set; }

    /// <summary>
    /// 按服务分组的调用数
    /// </summary>
    public Dictionary<string, long> CallsByService { get; set; } = new();
}

/// <summary>
/// 系统指标
/// </summary>
public class SystemMetrics
{
    /// <summary>
    /// 内存使用量（字节）
    /// </summary>
    public long MemoryUsage { get; set; }

    /// <summary>
    /// GC收集次数
    /// </summary>
    public Dictionary<int, int> GcCollections { get; set; } = new();

    /// <summary>
    /// 线程池信息
    /// </summary>
    public ThreadPoolInfo ThreadPool { get; set; } = new();

    /// <summary>
    /// 运行时间（毫秒）
    /// </summary>
    public long UptimeMilliseconds { get; set; }
}

/// <summary>
/// 线程池信息
/// </summary>
public class ThreadPoolInfo
{
    /// <summary>
    /// 可用工作线程数
    /// </summary>
    public int AvailableWorkerThreads { get; set; }

    /// <summary>
    /// 可用完成端口线程数
    /// </summary>
    public int AvailableCompletionPortThreads { get; set; }

    /// <summary>
    /// 最大工作线程数
    /// </summary>
    public int MaxWorkerThreads { get; set; }

    /// <summary>
    /// 最大完成端口线程数
    /// </summary>
    public int MaxCompletionPortThreads { get; set; }
}

/// <summary>
/// 指标收集器实现
/// </summary>
public class MetricsCollector : IMetricsCollector
{
    private readonly ILogger<MetricsCollector> _logger;
    private readonly ConcurrentDictionary<string, long> _counters = new();
    private readonly ConcurrentDictionary<string, List<double>> _histograms = new();
    private readonly ConcurrentDictionary<string, double> _gauges = new();
    private readonly ConcurrentQueue<ApiRequestRecord> _apiRequests = new();
    private readonly ConcurrentQueue<DatabaseOperationRecord> _databaseOperations = new();
    private readonly ConcurrentQueue<ExternalServiceCallRecord> _externalServiceCalls = new();

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="logger">日志记录器</param>
    public MetricsCollector(ILogger<MetricsCollector> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// 记录API请求
    /// </summary>
    public void RecordApiRequest(string endpoint, string method, int statusCode, TimeSpan duration)
    {
        var record = new ApiRequestRecord
        {
            Endpoint = endpoint,
            Method = method,
            StatusCode = statusCode,
            Duration = duration,
            Timestamp = DateTime.UtcNow
        };

        _apiRequests.Enqueue(record);

        // 限制队列大小
        while (_apiRequests.Count > 10000)
        {
            _apiRequests.TryDequeue(out _);
        }

        // 更新计数器
        IncrementCounter("api_requests_total", new Dictionary<string, string>
        {
            ["endpoint"] = endpoint,
            ["method"] = method,
            ["status_code"] = statusCode.ToString()
        });

        // 记录响应时间
        RecordHistogram("api_request_duration_ms", duration.TotalMilliseconds, new Dictionary<string, string>
        {
            ["endpoint"] = endpoint,
            ["method"] = method
        });
    }

    /// <summary>
    /// 记录数据库操作
    /// </summary>
    public void RecordDatabaseOperation(string operation, string table, TimeSpan duration, bool success)
    {
        var record = new DatabaseOperationRecord
        {
            Operation = operation,
            Table = table,
            Duration = duration,
            Success = success,
            Timestamp = DateTime.UtcNow
        };

        _databaseOperations.Enqueue(record);

        // 限制队列大小
        while (_databaseOperations.Count > 5000)
        {
            _databaseOperations.TryDequeue(out _);
        }

        // 更新计数器
        IncrementCounter("database_operations_total", new Dictionary<string, string>
        {
            ["operation"] = operation,
            ["table"] = table,
            ["success"] = success.ToString()
        });

        // 记录执行时间
        RecordHistogram("database_operation_duration_ms", duration.TotalMilliseconds, new Dictionary<string, string>
        {
            ["operation"] = operation,
            ["table"] = table
        });
    }

    /// <summary>
    /// 记录外部服务调用
    /// </summary>
    public void RecordExternalServiceCall(string serviceName, string operation, TimeSpan duration, bool success)
    {
        var record = new ExternalServiceCallRecord
        {
            ServiceName = serviceName,
            Operation = operation,
            Duration = duration,
            Success = success,
            Timestamp = DateTime.UtcNow
        };

        _externalServiceCalls.Enqueue(record);

        // 限制队列大小
        while (_externalServiceCalls.Count > 5000)
        {
            _externalServiceCalls.TryDequeue(out _);
        }

        // 更新计数器
        IncrementCounter("external_service_calls_total", new Dictionary<string, string>
        {
            ["service"] = serviceName,
            ["operation"] = operation,
            ["success"] = success.ToString()
        });

        // 记录响应时间
        RecordHistogram("external_service_call_duration_ms", duration.TotalMilliseconds, new Dictionary<string, string>
        {
            ["service"] = serviceName,
            ["operation"] = operation
        });
    }

    /// <summary>
    /// 增加计数器
    /// </summary>
    public void IncrementCounter(string name, Dictionary<string, string>? tags = null, long value = 1)
    {
        var key = BuildMetricKey(name, tags);
        _counters.AddOrUpdate(key, value, (k, v) => v + value);
    }

    /// <summary>
    /// 记录直方图值
    /// </summary>
    public void RecordHistogram(string name, double value, Dictionary<string, string>? tags = null)
    {
        var key = BuildMetricKey(name, tags);
        _histograms.AddOrUpdate(key, new List<double> { value }, (k, v) =>
        {
            v.Add(value);
            // 限制历史数据大小
            if (v.Count > 1000)
            {
                v.RemoveRange(0, v.Count - 1000);
            }
            return v;
        });
    }

    /// <summary>
    /// 设置仪表值
    /// </summary>
    public void SetGauge(string name, double value, Dictionary<string, string>? tags = null)
    {
        var key = BuildMetricKey(name, tags);
        _gauges.AddOrUpdate(key, value, (k, v) => value);
    }

    /// <summary>
    /// 获取指标摘要
    /// </summary>
    public MetricsSummary GetMetricsSummary()
    {
        var summary = new MetricsSummary();

        // 计算API请求指标
        var apiRequestList = _apiRequests.ToArray();
        if (apiRequestList.Any())
        {
            summary.ApiRequests.TotalRequests = apiRequestList.Length;
            summary.ApiRequests.SuccessfulRequests = apiRequestList.Count(r => r.StatusCode >= 200 && r.StatusCode < 400);
            summary.ApiRequests.FailedRequests = apiRequestList.Count(r => r.StatusCode >= 400);
            
            var durations = apiRequestList.Select(r => r.Duration.TotalMilliseconds).ToArray();
            if (durations.Any())
            {
                summary.ApiRequests.AverageResponseTime = durations.Average();
                summary.ApiRequests.MaxResponseTime = durations.Max();
                summary.ApiRequests.MinResponseTime = durations.Min();
            }

            summary.ApiRequests.RequestsByEndpoint = apiRequestList
                .GroupBy(r => r.Endpoint)
                .ToDictionary(g => g.Key, g => (long)g.Count());

            summary.ApiRequests.RequestsByStatusCode = apiRequestList
                .GroupBy(r => r.StatusCode)
                .ToDictionary(g => g.Key, g => (long)g.Count());
        }

        // 计算数据库指标
        var dbOperationList = _databaseOperations.ToArray();
        if (dbOperationList.Any())
        {
            summary.Database.TotalOperations = dbOperationList.Length;
            summary.Database.SuccessfulOperations = dbOperationList.Count(r => r.Success);
            summary.Database.FailedOperations = dbOperationList.Count(r => !r.Success);
            
            var durations = dbOperationList.Select(r => r.Duration.TotalMilliseconds).ToArray();
            if (durations.Any())
            {
                summary.Database.AverageExecutionTime = durations.Average();
            }

            summary.Database.OperationsByType = dbOperationList
                .GroupBy(r => r.Operation)
                .ToDictionary(g => g.Key, g => (long)g.Count());

            summary.Database.OperationsByTable = dbOperationList
                .GroupBy(r => r.Table)
                .ToDictionary(g => g.Key, g => (long)g.Count());
        }

        // 计算外部服务指标
        var externalCallList = _externalServiceCalls.ToArray();
        if (externalCallList.Any())
        {
            summary.ExternalServices.TotalCalls = externalCallList.Length;
            summary.ExternalServices.SuccessfulCalls = externalCallList.Count(r => r.Success);
            summary.ExternalServices.FailedCalls = externalCallList.Count(r => !r.Success);
            
            var durations = externalCallList.Select(r => r.Duration.TotalMilliseconds).ToArray();
            if (durations.Any())
            {
                summary.ExternalServices.AverageResponseTime = durations.Average();
            }

            summary.ExternalServices.CallsByService = externalCallList
                .GroupBy(r => r.ServiceName)
                .ToDictionary(g => g.Key, g => (long)g.Count());
        }

        // 计算系统指标
        summary.System.MemoryUsage = GC.GetTotalMemory(false);
        summary.System.GcCollections = new Dictionary<int, int>
        {
            [0] = GC.CollectionCount(0),
            [1] = GC.CollectionCount(1),
            [2] = GC.CollectionCount(2)
        };

        ThreadPool.GetAvailableThreads(out var availableWorkerThreads, out var availableCompletionPortThreads);
        ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads);
        
        summary.System.ThreadPool = new ThreadPoolInfo
        {
            AvailableWorkerThreads = availableWorkerThreads,
            AvailableCompletionPortThreads = availableCompletionPortThreads,
            MaxWorkerThreads = maxWorkerThreads,
            MaxCompletionPortThreads = maxCompletionPortThreads
        };

        summary.System.UptimeMilliseconds = Environment.TickCount64;

        return summary;
    }

    /// <summary>
    /// 构建指标键
    /// </summary>
    private string BuildMetricKey(string name, Dictionary<string, string>? tags)
    {
        if (tags == null || !tags.Any())
        {
            return name;
        }

        var tagString = string.Join(",", tags.Select(kvp => $"{kvp.Key}={kvp.Value}"));
        return $"{name}[{tagString}]";
    }
}

/// <summary>
/// API请求记录
/// </summary>
internal class ApiRequestRecord
{
    public string Endpoint { get; set; } = string.Empty;
    public string Method { get; set; } = string.Empty;
    public int StatusCode { get; set; }
    public TimeSpan Duration { get; set; }
    public DateTime Timestamp { get; set; }
}

/// <summary>
/// 数据库操作记录
/// </summary>
internal class DatabaseOperationRecord
{
    public string Operation { get; set; } = string.Empty;
    public string Table { get; set; } = string.Empty;
    public TimeSpan Duration { get; set; }
    public bool Success { get; set; }
    public DateTime Timestamp { get; set; }
}

/// <summary>
/// 外部服务调用记录
/// </summary>
internal class ExternalServiceCallRecord
{
    public string ServiceName { get; set; } = string.Empty;
    public string Operation { get; set; } = string.Empty;
    public TimeSpan Duration { get; set; }
    public bool Success { get; set; }
    public DateTime Timestamp { get; set; }
}
